﻿using System;
using System.Collections.Generic;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using YArchitech.Revit;
using YJKArch.NumberRoom;
using HYOpeningCommon.DbOpening;
using HYOpeningCommon.OpeningProfile;
using HYOpeningCommon.Public;

namespace HYOpeningCreate.Public
{
	public class FamilySymbolOperator
	{
		private FamilySymbol CreateFamilySymbolByTemplate(Family family, string strFamilyName, double dHAng, double dVAng, DbOpeningBase opening)
		{
			Document document = family.Document;
			Document document2 = document.EditFamily(family);
			if (document2 == null)
			{
				return null;
			}
			Wall wall = FamilySymbolOperator.GetElemByDoc(document2, typeof(Wall)) as Wall;
			if (wall == null)
			{
				return null;
			}
			double z = FamilySymbolOperator.GetElemLocationCurve(wall).GetEndPoint(0).Z;
			Sweep sweep = FamilySymbolOperator.GetElemByDoc(document2, typeof(Sweep)) as Sweep;
			if (sweep == null)
			{
				return null;
			}
			CurveArrArray profile = sweep.PathSketch.Profile;
			if (profile.Size < 1)
			{
				return null;
			}
            CurveArray curveArray = profile.get_Item(0);
			if (curveArray.Size < 1)
			{
				return null;
			}
            Curve curve = curveArray.get_Item(0);
			if (curve == null)
			{
				return null;
			}
			OpeningProfileRect openingProfileRect = opening.m_profile as OpeningProfileRect;
			if (openingProfileRect != null && dVAng.ToString("f1") != "90.0")
			{
				FamilySymbolOperator.SetOpeningSize(document2, openingProfileRect);
			}
			XYZ cvIntersect2WallOriPoint = FamilySymbolOperator.GetCvIntersect2WallOriPoint(curve, wall);
			if (cvIntersect2WallOriPoint == null)
			{
				return null;
			}
			if (!FamilySymbolOperator.RotateOpening(dHAng, dVAng, document2, cvIntersect2WallOriPoint, sweep))
			{
				return null;
			}
			return FamilySymbolOperator.ReNameFamilyAndFamilySymbol(strFamilyName, document, document2);
		}

		private static void SetOpeningSize(Autodesk.Revit.DB.Document docFamily, OpeningProfileRect proRec)
		{
			Transaction transaction = new Transaction(docFamily, "ModifyParam");
			transaction.Start();
			try
			{
				FamilyManager familyManager = docFamily.FamilyManager;
				double dExtendDist = proRec.m_dExtendDist;
				FamilyParameter familyParameter = familyManager.get_Parameter("洞口宽度");
				familyManager.Set(familyParameter, AssistFunc.mmToFeet(proRec.m_cutHeight + dExtendDist * 2.0));
				FamilyParameter familyParameter2 = familyManager.get_Parameter("洞口高度");
				familyManager.Set(familyParameter2, AssistFunc.mmToFeet(proRec.m_cutHeight + dExtendDist * 2.0));
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
			}
		}

		private static bool RotateOpening(double dHAng, double dVAng, Autodesk.Revit.DB.Document docFamily, XYZ ptOrigin, Element elemBody2Modify)
		{
			dHAng -= 90.0;
			dVAng -= 90.0;
			Transaction transaction = new Transaction(docFamily, "RotateElement");
			try
			{
				transaction.Start();
				Line line = Line.CreateUnbound(ptOrigin, ptOrigin + XYZ.BasisX);
				ElementTransformUtils.RotateElement(docFamily, elemBody2Modify.Id, line, dVAng * Math.PI / 180.0);
				Line line2 = Line.CreateUnbound(ptOrigin, ptOrigin + XYZ.BasisZ);
				ElementTransformUtils.RotateElement(docFamily, elemBody2Modify.Id, line2, dHAng * Math.PI / 180.0);
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
				return false;
			}
			return true;
		}

		private static XYZ GetCvIntersect2WallOriPoint(Curve cv, Wall wall)
		{
			List<XYZ> list = new List<XYZ>();
			try
			{
				XYZ endPoint = cv.GetEndPoint(0);
				XYZ endPoint2 = cv.GetEndPoint(1);
				XYZ zero = XYZ.Zero;
				XYZ zero2 = XYZ.Zero;
				if (!FamilySymbolOperator.GetElemLocationCurve(wall, ref zero, ref zero2))
				{
					return null;
				}
				double z = zero.Z;
				XYZ xyz = new XYZ(endPoint.X, endPoint.Y, z);
				XYZ xyz2 = new XYZ(endPoint2.X, endPoint2.Y, z);
				Curve curve = Line.CreateBound(xyz, xyz2);
				IntersectionResultArray intersectionResultArray = null;
				Curve elemLocationCurve = FamilySymbolOperator.GetElemLocationCurve(wall);
                if ((int)curve.Intersect(elemLocationCurve, out intersectionResultArray) != 8)
				{
					return null;
				}
				for (int i = 0; i < intersectionResultArray.Size; i++)
				{
					XYZ xyzpoint = intersectionResultArray.get_Item(i).XYZPoint;
					Curve curve2 = Line.CreateUnbound(xyzpoint, XYZ.BasisZ);
					IntersectionResultArray intersectionResultArray2 = null;
                    if ((int)curve2.Intersect(cv, out intersectionResultArray2) == 8 && intersectionResultArray2.Size > 0)
					{
						xyzpoint = intersectionResultArray2.get_Item(0).XYZPoint;
						list.Add(xyzpoint);
					}
				}
			}
			catch
			{
			}
			if (list.Count > 0)
			{
				return list[0];
			}
			return null;
		}

		private static void DelRestrict(Autodesk.Revit.DB.Document docFamily)
		{
			Transaction transaction = new Transaction(docFamily, "DelRestrict");
			transaction.Start();
			try
			{
				IList<Element> list = new FilteredElementCollector(docFamily).OfClass(typeof(Dimension)).ToElements();
				int count = list.Count;
				for (int i = 0; i < count; i++)
				{
					Dimension dimension = list[i] as Dimension;
					if (dimension.NumberOfSegments == 2)
					{
						docFamily.Delete(dimension.Id);
					}
				}
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
			}
		}

		private static FamilySymbol ReNameFamilyAndFamilySymbol(string strFamilyName, Autodesk.Revit.DB.Document doc, Autodesk.Revit.DB.Document docFamily)
		{
			FamilySymbol familySymbol = null;
			MyFamilyLoadOptions myFamilyLoadOptions = new MyFamilyLoadOptions();
			Family family = docFamily.LoadFamily(doc, myFamilyLoadOptions);
			Transaction transaction = new Transaction(doc, "ReNameFamily");
			try
			{
				transaction.Start();
				family.Name = strFamilyName;
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
			}
			docFamily.Close(false);
			if (family != null)
			{
				familySymbol = family.GetSymbols().FirstOrDefault<FamilySymbol>();
				Transaction transaction2 = new Transaction(doc, "ModifyFiSymbolName");
				transaction2.Start();
				try
				{
					familySymbol.Name = strFamilyName;
					transaction2.Commit();
				}
				catch
				{
					transaction2.RollBack();
				}
			}
			return familySymbol;
		}

		private static Element GetElemByDoc(Autodesk.Revit.DB.Document doc, Type typeElem)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeElem);
			IList<Element> list = filteredElementCollector.ToList<Element>();
			if (list.Count > 0)
			{
				return list[0];
			}
			return null;
		}

		private static bool GetElemLocationCurve(Element elem, ref XYZ ptStart, ref XYZ ptEnd)
		{
			Curve elemLocationCurve = FamilySymbolOperator.GetElemLocationCurve(elem);
			if (elemLocationCurve != null)
			{
				ptStart = elemLocationCurve.GetEndPoint(0);
				ptEnd = elemLocationCurve.GetEndPoint(1);
				return true;
			}
			return false;
		}

		private static Curve GetElemLocationCurve(Element elem)
		{
			if (elem == null)
			{
				return null;
			}
			LocationCurve locationCurve = elem.Location as LocationCurve;
			if (locationCurve == null)
			{
				return null;
			}
			return locationCurve.Curve;
		}

		private static double R2A(double dAngR)
		{
			return dAngR * 180.0 / Math.PI;
		}

		private bool CalWallOpeningFamilyName(out string strFamilyName)
		{
			strFamilyName = null;
			try
			{
				XYZ directionCutObj = this.m_DbOpeningBase.m_profile.m_directionCutObj;
				XYZ directionProfile = this.m_DbOpeningBase.m_profile.m_directionProfile;
				XYZ position = this.m_DbOpeningBase.m_profile.m_position;
				this.m_dHang = CommonInterface.GetPipe2WallHAng(directionCutObj, directionProfile, position);
				this.m_dVang = CommonInterface.GetPipe2WallVAng(directionCutObj, directionProfile, position);
				this.m_dHang = FamilySymbolOperator.R2A(this.m_dHang);
				this.m_dVang = FamilySymbolOperator.R2A(this.m_dVang);
				string name = this.m_DbOpeningBase.GetType().Name;
				if (name.CompareTo("DbCircleWallOpening") == 0)
				{
					strFamilyName = "圆形墙洞_HAng" + this.m_dHang.ToString("f1") + "_VAng" + this.m_dVang.ToString("f1");
				}
				else if (name.CompareTo("DbRectWallOpening") == 0)
				{
					OpeningProfileRect openingProfileRect = this.m_DbOpeningBase.m_profile as OpeningProfileRect;
					this.m_dWith = openingProfileRect.m_cutWidth + openingProfileRect.m_dExtendDist * 2.0;
					this.m_dHeight = openingProfileRect.m_cutHeight + openingProfileRect.m_dExtendDist * 2.0;
					strFamilyName = "矩形墙洞_HAng" + this.m_dHang.ToString("f1");
					if (this.m_dVang.ToString("f1") != "90.0")
					{
						strFamilyName = string.Concat(new string[]
						{
							strFamilyName,
							"_VAng",
							this.m_dVang.ToString("f1"),
							"_W",
							this.m_dWith.ToString("f1"),
							"_H",
							this.m_dHeight.ToString("f1")
						});
					}
				}
			}
			catch
			{
				return false;
			}
			return true;
		}

		private bool IsExistFamily(string strFamilyName)
		{
			Family family = ElementFiltering.FindFamily(this.m_doc, strFamilyName);
			if (family != null)
			{
				this.m_FamilySymbol = family.GetSymbols().FirstOrDefault<FamilySymbol>();
				return true;
			}
			return false;
		}

		private bool CalWallOpeningFamilySymbol()
		{
			string strFamilyName = null;
			if (!this.CalWallOpeningFamilyName(out strFamilyName))
			{
				return false;
			}
			if (this.IsExistFamily(strFamilyName))
			{
				return true;
			}
			this.m_FamilySymbol = this.CreateFamilySymbolByTemplate(this.m_FamilySymbol.Family, strFamilyName, this.m_dHang, this.m_dVang, this.m_DbOpeningBase);
			return this.m_FamilySymbol != null;
		}

		public FamilySymbolOperator(Autodesk.Revit.DB.Document doc, DbOpeningBase dbOpeningBase)
		{
			this.m_doc = doc;
			this.m_DbOpeningBase = dbOpeningBase;
		}

		public bool DoCalculate()
		{
			DbFamilyOpening dbFamilyOpening = this.m_DbOpeningBase as DbFamilyOpening;
			return dbFamilyOpening != null && dbFamilyOpening.LoadOpeningFamily(this.m_doc, ref this.m_FamilySymbol) && (!this.m_DbOpeningBase.IsNeedCreateFamily() || this.CalWallOpeningFamilySymbol());
		}

		public FamilySymbol GetFamilySymble()
		{
			return this.m_FamilySymbol;
		}

		public bool IsNeedSetSize()
		{
			bool result = true;
			if (this.m_DbOpeningBase is DbRectWallOpening && this.m_dVang.ToString("f1") != "90.0")
			{
				result = false;
			}
			return result;
		}

		private Document m_doc;

		private DbOpeningBase m_DbOpeningBase;

		private FamilySymbol m_FamilySymbol;

		private double m_dHang;

		private double m_dVang;

		private double m_dWith;

		private double m_dHeight;
	}
}
